`include "../../include/cpu_defines.sv"
`include "../../include/common.sv"

module AluIssueQueue
#(parameter BUFFER_SIZE = 8)(
	input logic cpu_clk,
	input logic cpu_rst_n,
	input logic clear,
	input logic stall,
	input logic en1,
	input logic en2,
	input logic inst1_branch,
	input logic inst2_branch,
	input logic [5: 0] inst1_rs,
	input logic [5: 0] inst2_rs,
	input logic [5: 0] inst1_rt,
	input logic [5: 0] inst2_rt,
	input logic [5: 0] inst1_rd,
	input logic [5: 0] inst2_rd,
	input logic [`EXC_CODE_BUS] inst1_exccode,
	input logic [`EXC_CODE_BUS] inst2_exccode,
	input logic inst1_rs_ready,
	input logic inst1_rt_ready,
	input logic inst2_rs_ready,
	input logic inst2_rt_ready,
	input logic [31: 0] inst1_src1,
	input logic [31: 0] inst1_src2,
	input logic [31: 0] inst2_src1,
	input logic [31: 0] inst2_src2,
	input logic [`ALUOP_BUS] inst1_aluop,
	input logic [`ALUOP_BUS] inst2_aluop,
	input logic [5: 0] rob_index1,
	input logic [5: 0] rob_index2,
	input logic [`BRANCH_BUFFER_WIDTH-1: 0] branch_index,
	input logic rob_direction1,
	input logic rob_direction2,
	input logic wb_en1,
	input logic wb_en2,
	input logic wb_en3,
	input logic [5: 0] wb_rd1,
	input logic [5: 0] wb_rd2,
	input logic [5: 0] wb_rd3,
	input logic [31: 0] wb_src1,
	input logic [31: 0] wb_src2,
	input logic [31: 0] wb_src3,
	input logic inst1_acceptable,
	input logic inst2_acceptable,
	input logic [31: 0] prf_src1,
	input logic [31: 0] prf_src2,
	input logic [31: 0] prf_src3,
	input logic [31: 0] prf_src4,
	`ifdef CPU_DEBUG
		input logic [31:0] debug_inst1_in,
		input logic [31:0] debug_inst2_in,
	`endif 
	output logic [5 :0] prf_rs1,
	output logic [5: 0] prf_rt1,
	output logic [5: 0] prf_rs2,
	output logic [5: 0] prf_rt2,
	output logic prf_en1,
	output logic prf_en2,
	output logic [5: 0] prf_rd1,
	output logic [5: 0] prf_rd2,
	output logic out_inst1_valid,
	output logic out_inst2_valid,
	output logic out_alu1_valid,
	output logic out_alu2_valid,
	output logic [5: 0] out_inst1_rd,
	output logic [5: 0] out_inst2_rd,
	output logic [31: 0] out_inst1_src1,
	output logic [31: 0] out_inst1_src2,
	output logic [31: 0] out_inst2_src1,
	output logic [31: 0] out_inst2_src2,
	output logic [5: 0] out_inst1_rob_index,
	output logic [5: 0] out_inst2_rob_index,
	output logic out_inst1_branch,
	output logic out_inst2_branch,
	output logic [3: 0] out_inst1_branch_index,
	output logic [3: 0] out_inst2_branch_index,
	output logic [`ALUOP_BUS] out_inst1_aluop,
	output logic [`ALUOP_BUS] out_inst2_aluop,
	output logic [`EXC_CODE_BUS] out_inst1_exccode,
	output logic [`EXC_CODE_BUS] out_inst2_exccode,
	output logic dis_alu_stall_request
);
	logic bank_select, exchange;
	logic bank0_en, bank1_en;
	logic exchange_en1, exchange_en2;
	logic [4: 0] banks_remain;
	logic input_rs_ready1, input_rs_ready2, input_rt_ready1, input_rt_ready2;
	logic bank0_valid, bank1_valid;
	logic bank0_full, bank1_full;
	logic bank0_branch, bank1_branch;
	logic select_bank0, select_bank1;
	logic [3: 0] bank0_branch_index, bank1_branch_index;
	logic [5: 0] bank0_rs, bank0_rt, bank1_rs, bank1_rt;
	logic [5: 0] bank0_rd, bank1_rd, bank0_rob_index, bank1_rob_index;
	logic [`ALUOP_BUS] bank0_aluop, bank1_aluop;
	logic [31: 0] bank0_src1, bank0_src2, bank1_src1, bank1_src2;
	logic [`EXC_CODE_BUS] bank0_exccode, bank1_exccode;

	logic prf_branch1, prf_branch2;
	logic [5: 0] prf_rob_index1, prf_rob_index2;
	logic [`BRANCH_BUFFER_WIDTH-1: 0] prf_branch_index1, prf_branch_index2;
	logic [`ALUOP_BUS] prf_aluop1, prf_aluop2;
	logic[31: 0] prf_bank0_src1, prf_bank0_src2, prf_bank1_src1, prf_bank1_src2;
	logic [`EXC_CODE_BUS] prf_exccode1, prf_exccode2;

	assign dis_alu_stall_request = exchange_en1 & bank0_full | exchange_en2 & bank1_full;
	assign out_alu1_valid = prf_en1 & ~clear;
	assign out_alu2_valid = prf_en2 & ~clear;
	assign bank_select = en1 ^ en2;
	assign select_bank0 = bank_select & ~banks_remain[4] & en2 | en1 & en2 & banks_remain[4];
	assign select_bank1 = bank_select & banks_remain[4] & en1 | en1 & en2 & banks_remain[4];
	assign exchange = en1 & ~en2 & banks_remain[4] | ~en1 & en2 & ~banks_remain[4] | en1 & en2 & banks_remain[4];
	assign exchange_en1 = exchange ? en2 : en1;
	assign exchange_en2 = exchange ? en1 : en2;
	assign bank0_en = exchange_en1 & ~stall;
	assign bank1_en = exchange_en2 & ~stall;
	assign input_rs_ready1 = inst1_rs_ready || (prf_en1 && inst1_rs == prf_rd1) || (prf_en2 && inst1_rs == prf_rd2);
	assign input_rt_ready1 = inst1_rt_ready || prf_en1 && inst1_rt == prf_rd1 || prf_en2 && inst1_rt == prf_rd2;
	assign input_rs_ready2 = inst2_rs_ready || prf_en1 && inst2_rs == prf_rd1 || prf_en2 && inst2_rs == prf_rd2;
	assign input_rt_ready2 = inst2_rt_ready || prf_en1 && inst2_rt == prf_rd1 || prf_en2 && inst2_rt == prf_rd2;

	AluBank bank0(
		.cpu_clk(cpu_clk),
		.cpu_rst_n(cpu_rst_n),
		.clear(clear),
		.en(bank0_en),
		.branch(exchange ? inst2_branch : inst1_branch),
		.rs_ready(exchange ? input_rs_ready2 : input_rs_ready1),
		.rt_ready(exchange ? input_rt_ready2 : input_rt_ready1),
		.rs(exchange ? inst2_rs : inst1_rs),
		.rt(exchange ? inst2_rt : inst1_rt),
		.rd(exchange ? inst2_rd : inst1_rd),
		.rob_index(exchange ? rob_index2 : rob_index1),
		.branch_index(branch_index),
		.exccode(exchange ? inst2_exccode : inst1_exccode),
		.direction(exchange ? rob_direction2 : rob_direction1),
		.src1(exchange ? inst2_src1: inst1_src1),
		.src2(exchange ? inst2_src2 : inst1_src2),
		.aluop(exchange ? inst2_aluop : inst1_aluop),
		.wb_en1(wb_en1),
		.wb_en2(wb_en2),
		.wb_en3(wb_en3),
		.wb_rd1(wb_rd1),
		.wb_rd2(wb_rd2),
		.wb_rd3(wb_rd3),
		.bank0_en(prf_en1),
		.bank0_rd(prf_rd1),
		.bank1_en(prf_en2),
		.bank1_rd(prf_rd2),
`ifdef CPU_DEBUG
		.debug_inst_in(debug_inst1_in),
`endif 
		.full(bank0_full),
		.out_en(bank0_valid),
		.out_branch(bank0_branch),
		.out_rs(bank0_rs),
		.out_rt(bank0_rt),
		.out_rd(bank0_rd),
		.out_rob_index(bank0_rob_index),
		.out_exccode(bank0_exccode),
		.out_aluop(bank0_aluop),
		.out_src1(bank0_src1),
		.out_src2(bank0_src2),
		.out_branch_index(bank0_branch_index)
	);

	AluBank bank1(
		.cpu_clk(cpu_clk),
		.cpu_rst_n(cpu_rst_n),
		.clear(clear),
		.en(bank1_en),
		.branch(exchange ? inst1_branch : inst2_branch),
		.rs_ready(exchange ? input_rs_ready1 : input_rs_ready2),
		.rt_ready(exchange ? input_rt_ready1 : input_rt_ready2),
		.rs(exchange ? inst1_rs : inst2_rs),
		.rt(exchange ? inst1_rt : inst2_rt),
		.rd(exchange ? inst1_rd : inst2_rd),
		.rob_index(exchange ? rob_index1 : rob_index2),
		.branch_index(branch_index),
		.exccode(exchange ? inst1_exccode : inst2_exccode),
		.direction(exchange ? rob_direction1 : rob_direction2),
		.src1(exchange ? inst1_src1 : inst2_src1),
		.src2(exchange ? inst1_src2 : inst2_src2),
		.aluop(exchange ? inst1_aluop : inst2_aluop),
		.wb_en1(wb_en1),
		.wb_en2(wb_en2),
		.wb_en3(wb_en3),
		.wb_rd1(wb_rd1),
		.wb_rd2(wb_rd2),
		.wb_rd3(wb_rd3),
		.bank0_en(prf_en1),
		.bank0_rd(prf_rd1),
		.bank1_en(prf_en2),
		.bank1_rd(prf_rd2),
`ifdef CPU_DEBUG
		.debug_inst_in(debug_inst2_in),
`endif 
		.full(bank1_full),
		.out_en(bank1_valid),
		.out_branch(bank1_branch),
		.out_rs(bank1_rs),
		.out_rt(bank1_rt),
		.out_rd(bank1_rd),
		.out_rob_index(bank1_rob_index),
		.out_exccode(bank1_exccode),
		.out_aluop(bank1_aluop),
		.out_src1(bank1_src1),
		.out_src2(bank1_src2),
		.out_branch_index(bank1_branch_index)
	);

	always_ff @(posedge cpu_clk)begin
		if(cpu_rst_n == 1'b0 || clear)begin
			banks_remain <= 5'b10000;
			out_inst1_valid <= 0;
			out_inst2_valid <= 0;
			out_inst1_rd <= 0;
			out_inst2_rd <= 0;
			out_inst1_src1 <= 0;
			out_inst1_src2 <= 0;
			out_inst2_src1 <= 0;
			out_inst2_src2 <= 0;
			out_inst1_rob_index <= 0;
			out_inst2_rob_index <= 0;
			out_inst1_branch <= 0;
			out_inst2_branch <= 0;
			out_inst1_branch_index <= 0;
			out_inst2_branch_index <= 0;
			out_inst1_aluop <= 0;
			out_inst2_aluop <= 0;
			out_inst1_exccode <= `EXC_NONE;
			out_inst2_exccode <= `EXC_NONE;
			prf_en1 <= 0;
			prf_en2 <= 0;
			prf_rs1 <= 0;
			prf_rs2 <= 0;
			prf_rt1 <= 0;
			prf_rt2 <= 0;
			prf_rd1 <= 0;
			prf_rd2 <= 0;
			prf_bank0_src1 <= 0;
			prf_bank0_src2 <= 0;
			prf_bank1_src1 <= 0;
			prf_bank1_src2 <= 0;
			prf_rob_index1 <= 0;
			prf_rob_index2 <= 0;
			prf_branch1 <= 0;
			prf_branch2 <= 0;
			prf_branch_index1 <= 0;
			prf_branch_index2 <= 0;
			prf_aluop1 <= 0;
			prf_aluop2 <= 0;
			prf_exccode1 <= `EXC_NONE;
			prf_exccode2 <= `EXC_NONE;
		end
		else begin
			banks_remain <= banks_remain + bank0_en - bank1_en - bank0_valid + bank1_valid;

			prf_en1 <= bank0_valid;
			prf_en2 <= bank1_valid;
			prf_branch1 <= bank0_branch;
			prf_branch2 <= bank1_branch;
			prf_rs1 <= bank0_rs;
			prf_rt1 <= bank0_rt;
			prf_rs2 <= bank1_rs;
			prf_rt2 <= bank1_rt;
			prf_rd1 <= bank0_rd;
			prf_rd2 <= bank1_rd;
			prf_bank0_src1 <= bank0_src1;
			prf_bank0_src2 <= bank0_src2;
			prf_bank1_src1 <= bank1_src1;
			prf_bank1_src2 <= bank1_src2;
			prf_rob_index1 <= bank0_rob_index;
			prf_rob_index2 <= bank1_rob_index;
			prf_branch_index1 <= bank0_branch_index;
			prf_branch_index2 <= bank1_branch_index;
			prf_aluop1 <= bank0_aluop;
			prf_aluop2 <= bank1_aluop;
			prf_exccode1 <= bank0_exccode;
			prf_exccode2 <= bank1_exccode;

			out_inst1_valid <= prf_en1;
			out_inst2_valid <= prf_en2;
			out_inst1_rd <= prf_rd1;
			out_inst2_rd <= prf_rd2;
			out_inst1_src1 <= prf_rs1 == 0 ? prf_bank0_src1 :
								wb_en1 && wb_rd1 == prf_rs1 ? wb_src1 :
								wb_en2 && wb_rd2 == prf_rs1 ? wb_src2 :
								wb_en3 && wb_rd3 == prf_rs1 ? wb_src3 :
								prf_src1;
			out_inst1_src2 <= prf_rt1 == 0 ? prf_bank0_src2 :
								wb_en1 && wb_rd1 == prf_rt1 ? wb_src1 :
								wb_en2 && wb_rd2 == prf_rt1 ? wb_src2 :
								wb_en3 && wb_rd3 == prf_rt1 ? wb_src3 :
								prf_src2;
			out_inst2_src1 <= prf_rs2 == 0 ? prf_bank1_src1 :
								wb_en1 && wb_rd1 == prf_rs2 ? wb_src1 :
								wb_en2 && wb_rd2 == prf_rs2 ? wb_src2 :
								wb_en3 && wb_rd3 == prf_rs2 ? wb_src3 :
								prf_src3;
			out_inst2_src2 <= prf_rt2 == 0 ? prf_bank1_src2 :
								wb_en1 && wb_rd1 == prf_rt2 ? wb_src1 :
								wb_en2 && wb_rd2 == prf_rt2 ? wb_src2 :
								wb_en3 && wb_rd3 == prf_rt2 ? wb_src3 :
								prf_src4;
			out_inst1_aluop <= prf_aluop1;
			out_inst2_aluop <= prf_aluop2;
			out_inst1_rob_index <= prf_rob_index1;
			out_inst2_rob_index <= prf_rob_index2;
			out_inst1_branch_index <= prf_branch_index1;
			out_inst2_branch_index <= prf_branch_index2;
			out_inst1_exccode <= prf_exccode1;
			out_inst2_exccode <= prf_exccode2;
			out_inst1_branch <= prf_branch1;
			out_inst2_branch <= prf_branch2;
		end
	end

endmodule

module AluBank #(
	parameter BANK_NUM=8
)(
	input logic cpu_clk,
	input logic cpu_rst_n,
	input logic clear,
	input logic en,
	input logic branch,
	input logic rs_ready,
	input logic rt_ready,
	input logic [5: 0] rs,
	input logic [5: 0] rt,
	input logic [5: 0] rd,
	input logic [5: 0] rob_index,
	input logic [`BRANCH_BUFFER_WIDTH-1: 0] branch_index,
	input logic [`EXC_CODE_BUS] exccode,
	input logic direction,
	input logic [31: 0] src1,
	input logic [31: 0] src2,
	input logic [`ALUOP_BUS] aluop,
	input logic wb_en1,
	input logic wb_en2,
	input logic wb_en3,
	input logic [5: 0] wb_rd1,
	input logic [5: 0] wb_rd2,
	input logic [5: 0] wb_rd3,
	input logic bank0_en,
	input logic [5: 0] bank0_rd,
	input logic bank1_en,
	input logic [5: 0] bank1_rd,
`ifdef CPU_DEBUG
		input logic [31:0] debug_inst_in,
`endif 
	output logic full,
	output logic out_en,
	output logic out_branch,
	output logic [5: 0] out_rs,
	output logic [5: 0] out_rt,
	output logic [5: 0] out_rd,
	output logic [`EXC_CODE_BUS] out_exccode,
	output logic [5: 0] out_rob_index,
	output logic [`ALUOP_BUS] out_aluop,
	output logic [31: 0] out_src1,
	output logic [31: 0] out_src2,
	output logic [3: 0] out_branch_index
);
	typedef struct packed{
		logic branch;
		logic [5: 0] rd;
		logic [5: 0] rob_index;
		logic [`BRANCH_BUFFER_WIDTH-1: 0] branch_index;
		logic [`ALUOP_BUS] aluop;
		logic [`EXC_CODE_BUS] exccode;
		logic [31: 0] src1;
		logic [31: 0] src2;
	} issue_element_t;

	logic [5: 0] buffer_rs[BANK_NUM-1: 0];
	logic [5: 0] buffer_rt[BANK_NUM-1: 0];
`ifdef CPU_DEBUG
	logic [31:0] debug_inst_buffer[BANK_NUM-1: 0];
`endif 
	logic [BANK_NUM-1: 0] buffer_en, free_index;
	logic [BANK_NUM-1: 0] buffer_rs_ready, buffer_rt_ready;
	logic [BANK_NUM-1: 0] ready;
	logic [BANK_NUM-1: 0][5: 0] buffer_index;
	logic [BANK_NUM-1: 0] buffer_direction;
	logic [BANK_NUM-1: 0] select_index;
	logic [2: 0] select_index_encode, free_index_encode;

	SDPRAM #(
		.WORD_WIDTH(94),
		.DEPTH(BANK_NUM),
		.ADDR_WIDTH(3)
	)buffer_ram(
		.clk(cpu_clk),
		.ena(en),
		.addra(free_index_encode),
		.wea(en),
		.dina({branch, rd, rob_index, branch_index, aluop, exccode, src1, src2}),
		.enb(1'b1),
		.addrb(select_index_encode),
		.doutb({out_branch, out_rd, out_rob_index, out_branch_index, out_aluop, out_exccode, out_src1, out_src2})
	);

	assign full = &buffer_en;
	assign ready = buffer_en & buffer_rs_ready & buffer_rt_ready;
	assign out_en = |select_index;
	assign out_rs = buffer_rs[select_index_encode];
	assign out_rt = buffer_rt[select_index_encode];
	priority_selector8 selector_free_index(~buffer_en, free_index);
	AluCompareUtil#(.BANK_NUM(BANK_NUM)) compare_util(ready, buffer_index, buffer_direction, select_index);
	encoder_8to3 encoder_free_index(free_index, free_index_encode);
	encoder_8to3 encoder_select_index(select_index, select_index_encode);

	always_ff @(posedge cpu_clk)begin
		if(cpu_rst_n == 1'b0 || clear)begin
			buffer_en <= 0;
			buffer_rs_ready <= 0;
			buffer_rt_ready <= 0;
			buffer_index <= 0;
			buffer_direction <= 0;
			for(int i=0; i<BANK_NUM; i++)begin
				buffer_rs[i] <= 0;
				buffer_rt[i] <=	0;
`ifdef CPU_DEBUG
				debug_inst_buffer[i] <= 0;
`endif 
			end
		end
		else begin
			if(en)begin
				buffer_rs_ready[free_index_encode] <= rs_ready;
				buffer_rt_ready[free_index_encode] <= rt_ready;
				buffer_rs[free_index_encode] <= rs;
				buffer_rt[free_index_encode] <= rt;
				buffer_index[free_index_encode] <= rob_index;
				buffer_direction[free_index_encode] <= direction;
`ifdef CPU_DEBUG
				debug_inst_buffer[free_index_encode] <= debug_inst_in;
`endif 
			end

			buffer_en <= (buffer_en | {BANK_NUM{en}} & free_index) & ~select_index;

			for(int i=0; i<BANK_NUM; i++)begin
				if(buffer_en[i])begin
					buffer_rs_ready[i] <= buffer_rs_ready[i] || (wb_en1 && buffer_rs[i] == wb_rd1) || (wb_en2 && buffer_rs[i] == wb_rd2) || (wb_en3 && buffer_rs[i] == wb_rd3) || (bank0_en && buffer_rs[i] == bank0_rd) || (bank1_en && buffer_rs[i] == bank1_rd);
					buffer_rt_ready[i] <= buffer_rt_ready[i] || (wb_en1 && buffer_rt[i] == wb_rd1) || (wb_en2 && buffer_rt[i] == wb_rd2) || (wb_en3 && buffer_rt[i] == wb_rd3) || (bank0_en && buffer_rt[i] == bank0_rd) || (bank1_en && buffer_rt[i] == bank1_rd);
				end
			end
		end
	end


endmodule

module AluCompareUtil #(
	parameter BANK_NUM=6
)(
	input logic [BANK_NUM-1: 0] ready,
	input logic [BANK_NUM-1: 0][5: 0] index,
	input logic [BANK_NUM-1: 0] direction,
	output logic [BANK_NUM-1: 0] select
);
	logic [27: 0] bigger;
	assign bigger[0] = ((direction[0] ^ direction[1]) ^ (index[0] < index[1]));
	assign bigger[1] = ((direction[0] ^ direction[2]) ^ (index[0] < index[2]));
	assign bigger[2] = ((direction[0] ^ direction[3]) ^ (index[0] < index[3]));
	assign bigger[3] = ((direction[0] ^ direction[4]) ^ (index[0] < index[4]));
	assign bigger[4] = ((direction[0] ^ direction[5]) ^ (index[0] < index[5]));
	assign bigger[5] = ((direction[0] ^ direction[6]) ^ (index[0] < index[6]));
	assign bigger[6] = ((direction[0] ^ direction[7]) ^ (index[0] < index[7]));
	assign bigger[7] = ((direction[1] ^ direction[2]) ^ (index[1] < index[2]));
	assign bigger[8] = ((direction[1] ^ direction[3]) ^ (index[1] < index[3]));
	assign bigger[9] = ((direction[1] ^ direction[4]) ^ (index[1] < index[4]));
	assign bigger[10] = ((direction[1] ^ direction[5]) ^ (index[1] < index[5]));
	assign bigger[11] = ((direction[1] ^ direction[6]) ^ (index[1] < index[6]));
	assign bigger[12] = ((direction[1] ^ direction[7]) ^ (index[1] < index[7]));
	assign bigger[13] = ((direction[2] ^ direction[3]) ^ (index[2] < index[3]));
	assign bigger[14] = ((direction[2] ^ direction[4]) ^ (index[2] < index[4]));
	assign bigger[15] = ((direction[2] ^ direction[5]) ^ (index[2] < index[5]));
	assign bigger[16] = ((direction[2] ^ direction[6]) ^ (index[2] < index[6]));
	assign bigger[17] = ((direction[2] ^ direction[7]) ^ (index[2] < index[7]));
	assign bigger[18] = ((direction[3] ^ direction[4]) ^ (index[3] < index[4]));
	assign bigger[19] = ((direction[3] ^ direction[5]) ^ (index[3] < index[5]));
	assign bigger[20] = ((direction[3] ^ direction[6]) ^ (index[3] < index[6]));
	assign bigger[21] = ((direction[3] ^ direction[7]) ^ (index[3] < index[7]));
	assign bigger[22] = ((direction[4] ^ direction[5]) ^ (index[4] < index[5]));
	assign bigger[23] = ((direction[4] ^ direction[6]) ^ (index[4] < index[6]));
	assign bigger[24] = ((direction[4] ^ direction[7]) ^ (index[4] < index[7]));
	assign bigger[25] = ((direction[5] ^ direction[6]) ^ (index[5] < index[6]));
	assign bigger[26] = ((direction[5] ^ direction[7]) ^ (index[5] < index[7]));
	assign bigger[27] = ((direction[6] ^ direction[7]) ^ (index[6] < index[7]));

	
	assign select[0] = ready[0] & ((~ready[1]) | ready[1] & bigger[0]) & ((~ready[2]) | ready[2] & bigger[1]) & ((~ready[3]) | ready[3] & bigger[2]) & ((~ready[4]) | ready[4] & bigger[3]) & ((~ready[5]) | ready[5] & bigger[4]) & (~ready[6] | ready[6] & bigger[5]) & (~ready[7] | ready[7] & bigger[6]);
	assign select[1] = ready[1] & (~ready[0] | ready[0] & ~bigger[0]) & (~ready[2] | ready[2] & bigger[7]) & (~ready[3] | ready[3] & bigger[8]) & (~ready[4] | ready[4] & bigger[9]) & (~ready[5] | ready[5] & bigger[10]) & (~ready[6] | ready[6] & bigger[11]) & (~ready[7] | ready[7] & bigger[12]);
	assign select[2] = ready[2] & (~ready[0] | ready[0] & ~bigger[1]) & (~ready[1] | ready[1] & ~bigger[7]) & (~ready[3] | ready[3] & bigger[13]) & (~ready[4] | ready[4] & bigger[14]) & (~ready[5] | ready[5] & bigger[15]) & (~ready[6] | ready[6] & bigger[16]) & (~ready[7] | ready[7] & bigger[17]);
	assign select[3] = ready[3] & (~ready[0] | ready[0] & ~bigger[2]) & (~ready[1] | ready[1] & ~bigger[8]) & (~ready[2] | ready[2] & ~bigger[13]) & (~ready[4] | ready[4] & bigger[18]) & (~ready[5] | ready[5] & bigger[19]) & (~ready[6] | ready[6] & bigger[20]) & (~ready[7] | ready[7] & bigger[21]);
	assign select[4] = ready[4] & (~ready[0] | ready[0] & ~bigger[3]) & (~ready[1] | ready[1] & ~bigger[9]) & (~ready[2] | ready[2] & ~bigger[14]) & (~ready[3] | ready[3] & ~bigger[18]) & (~ready[5] | ready[5] & bigger[22]) & (~ready[6] | ready[6] & bigger[23]) & (~ready[7] | ready[7] & bigger[24]);
	assign select[5] = ready[5] & (~ready[0] | ready[0] & ~bigger[4]) & (~ready[1] | ready[1] & ~bigger[10]) & (~ready[2] | ready[2] & ~bigger[15]) & (~ready[3] | ready[3] & ~bigger[19]) & (~ready[4] | ready[4] & ~bigger[22]) & (~ready[6] | ready[6] & bigger[25]) & (~ready[7] | ready[7] & bigger[26]);
	assign select[6] = ready[6] & (~ready[0] | ready[0] & ~bigger[5]) & (~ready[1] | ready[1] & ~bigger[11]) & (~ready[2] | ready[2] & ~bigger[16]) & (~ready[3] | ready[3] & ~bigger[20]) & (~ready[4] | ready[4] & ~bigger[23]) & (~ready[5] | ready[5] & ~bigger[25]) & (~ready[7] | ready[7] & bigger[27]);
	assign select[7] = ready[7] & (~ready[0] | ready[0] & ~bigger[6]) & (~ready[1] | ready[1] & ~bigger[12]) & (~ready[2] | ready[2] & ~bigger[17]) & (~ready[3] | ready[3] & ~bigger[21]) & (~ready[4] | ready[4] & ~bigger[24]) & (~ready[5] | ready[5] & ~bigger[26]) & (~ready[6] | ready[6] & ~bigger[27]);
endmodule